import org.springframework.core.io.DefaultResourceLoader as DRL
import org.springframework.util.AntPathMatcher

import org.apache.avalon.fortress.util.dag.Vertex
import org.apache.avalon.fortress.util.dag.DirectedAcyclicGraphVerifier as DAG
import org.apache.avalon.fortress.util.dag.CyclicDependencyException

import gant.Gant

import scripts.Utils

def APM = new AntPathMatcher()

def selectedProjects = []
def usedArguments = []

def projectProperties = [:]
// Get dependencies for each project
def vertices = [:]
def projectNames = [:]


new File("projects").eachDir {
	dir ->
	
	def projectName = dir.name
	
	projectProperties."${dir.absolutePath}" = Utils.getProjectProperties( dir.absolutePath )
	projectNames."${dir.absolutePath}" = projectName
	
	this.args.each {
		arg ->
				
		if (arg.startsWith("p:") && APM.match(arg.substring(2, arg.length()), dir.name)) {
			selectedProjects.add(dir.absolutePath)
			usedArguments.add(arg)
		}
	}
}

def targets = []

args.each {
	arg ->
	
	if (!usedArguments.contains(arg)) {
		targets.add(arg)
	}
}

// Check the build order for each project
// This is overkill but it's so dumb it's safe

def cl = {
	project, properties ->
	
	def projectName = projectNames."${project}"
	assert projectName != null
	vertices."${projectName}" = vertices."${projectName}" ? vertices."${projectName}" : new Vertex( project )
	def vertex = vertices."${projectName}"
	assert vertex != null
	
	properties.deps?.each {
		dep ->
		
		def depLocation = new File("projects/${dep}")
		
		if (!depLocation.exists() || !depLocation.directory || !projectProperties."${depLocation.absolutePath}") {
			throw new IllegalArgumentException("Unknown project [${dep}] specified as dependency for project [${projectName}]")
		}
		
		vertices."${dep}" = vertices."${dep}" ? vertices."${dep}" : new Vertex( depLocation.absolutePath )
		def depVertex = vertices."${dep}"
		assert depVertex != null
		vertex.addDependency( depVertex )
		println("Adding ${dep} to ${projectName}")
	}
}

def clWrap = {
	project, properties ->

	try {
		cl( project, properties )
	} catch(RuntimeException e) {
		e.printStackTrace()
		throw e
	}
}

selectedProjects.each {
	p ->
	
	clWrap( p, projectProperties."${p}" )
}

vertices.each {
	entry ->
	
	try {
		DAG.verify( entry.value )
	} catch (CyclicDependencyException e) {
		throw new RuntimeException("Found cyclic dependency between projects: ${e.message}")
	}
}


def projectCount = 0

while (projectCount < vertices.values().size()) {
	projectCount = vertices.values().size()
	
	def tmp = vertices.values().toList()

	DAG.topologicalSort( tmp )

	tmp.each {
		vertex ->
		
		clWrap( vertex.node, projectProperties."${vertex.node}" )
	}
}

def dependencies = vertices.values().toList()

DAG.topologicalSort( dependencies )

dependencies.each {
	print( "${it.node} -> " )
}

println()

dependencies.each {
	vertex ->
	
	def projectLocation = vertex.node
	
	// Call Gant script
	def arguments = []
	arguments.add("-f")
	arguments.add("scripts/BuildProject.groovy")
	arguments.add("-D")
	arguments.add("projectLocation=${projectLocation}")
	arguments.addAll(targets)
	
	Gant.main(arguments as String[])
}

if (dependencies.size() == 0) {
	def arguments = []

	println( targets )
	
	arguments.add("-f")
	arguments.add("scripts/UtilTargets.groovy")
	arguments.addAll( targets )
	
	Gant.main( arguments as String[] )
}

